require "Battle/Entity/EntityInfo"
require "Battle/MapLinkCtr"
require "Battle/Manager/EffectManager"
require "View/UIBase/UIComponent/UIComponentScrollRectEx"

BattleScene = {};
local this = BattleScene;
local mapId = 0;
local mapInfo = nil;
local battleMapCfg = nil;
local mapInstanse = nil;
local fightTimer = nil;
local fightTimerState = false;
---@type Entity[]
local tab_MonsterList = {};
---@type Entity[]
local tab_HeroList = {};
local uPheroMax = 5
local fighterMap = {};

local battleMainRoot = nil;
local cameraMain = nil;
local cameraMainTweenParams = nil
local bgComponent = nil

local stateIndex = 0

local skeletonAnimStateUserDataString = {}

local resList = {}

BattleScene.isShow = true

EnumConst.BattleSceneStateEnum = {
	NONE = 0,
	ENTERSCENE = 1,
	BATTLETIME1 = 2,
	MOVETIME1 = 3,
	BATTLETIME2 = 4,
	MOVETIME2 = 5,
	BATTLETIME3 = 6,
	BATTLECONTINUE = 7,
	LEAVESCENE = 8,
}
local battleState;

function BattleScene.init()
	battleMainRoot = panelMgr.BattleMain;
	cameraMain = battleMainRoot.transform:Find("CameraMain");
	Util.Lua_SetLocalPositionXYZ(cameraMain,0,15,-18);
	FightManager.setCamera(cameraMain:GetComponent("Camera"));
	SpineEffectManager.init();
	ShaderEffectManager.init();
	EnumConst.FIGHT_INNER_ROUND = HelperFunc.GetGlobalVlue(54)

	Util.resetRandomFac(999999);
	fightTimer = nil;

	battleState = EnumConst.BattleSceneStateEnum.NONE;

	cameraMainTweenParams = DG.Tweening.TweenParams.New()
	cameraMainTweenParams:SetEase(DG.Tweening.Ease.Linear)
end

function BattleScene.start()
	Time.timeScale = 1;
	--[[if fightTimer == nil then
        fightTimer = Timer.New(this.onUpdate,0.033,999999,false);
    else
        fightTimer:Reset(this.onUpdate,0.033,999999,false);
	end
	battleMainRoot = panelMgr.BattleMain;
	cameraMain = battleMainRoot.transform:Find("CameraMain");
	battleMainRoot.transform.gameObject:SetActive(true);
	fightTimer:Start();
	fightTimerState = true;
	this.changeState(EnumConst.BattleSceneStateEnum.ENTERSCENE);]]
	battleMainRoot = panelMgr.BattleMain;
	cameraMain = battleMainRoot.transform:Find("CameraMain");
	battleMainRoot.transform.gameObject:SetActive(true);
	local pos = decodeJsonStrToTabel(battleMapCfg["f_CameraPos1"]);
	Util.Lua_SetLocalPositionXYZ(cameraMain,pos[1],pos[2],-18);
	if mapInstanse~=nil then
		MapLinkCtr.reset();
	end
	this.AddBgLayer()
end

function BattleScene.pause()
	if fightTimer ~= nil then
		fightTimer:Stop();
		fightTimerState = false;
	end
end

function BattleScene.stop()
	if fightTimer ~= nil then
        fightTimer:Stop();
		fightTimerState = false;
	end
	battleMainRoot = panelMgr.BattleMain;
	-- log('BattleScene.stop')
	if battleMainRoot ~= nil then
		cameraMain = battleMainRoot.transform:Find("CameraMain");
		battleMainRoot.transform.gameObject:SetActive(false)	
		BattleSceneCacheResouce:ClearCacheRes()	
	end
	
	this.pause()
end

function BattleScene.isPlay()
	return fightTimerState;
end


function BattleScene.loadScene( successFunc , ishard)
	if mapInstanse ~= nil then
		MapLinkCtr.stop();
		--destroy(mapInstanse);
		--mapInstanse = nil;
	end

	local mapName;
	if not ishard then
		mapId = tostring(logicMgr.MapManager.getMapId());
		mapName = logicMgr.MapManager.getBattleMapName();
		battleMapCfg = G.dataTable["t_battlemap"][mapId];
	else
		mapId = tostring(logicMgr.StoryHardManager.getDungeonId());
		mapName = logicMgr.StoryHardManager.getBattleMapName();
	end
	
    ----------------------------------------------
    if UILoading and not FightManager.isRePlay then 
        resMgr:ClearBattleResRef()

        local refResList = UILoading.GetLoadModelResList()
        
        for i=1,#refResList do
            local array = string.split(refResList[i], "#")
            if #array > 1 then
                if array[2] == "Effect" then
                    resMgr:UpdateResTime(array[1], "Model")
                else
                    resMgr:UpdateResTime(array[1], array[2])
                end
            end
        end

		local useSkinId = logicMgr.HeroManager.GetRoleInfo("pic")
		--local useSkinId = logicMgr.SkinManager.getHeroSkinId(heroID)
    	local path = logicMgr.SkinManager.GetHeroDrawPathBySkinId(useSkinId);

		resMgr:UpdateResTime(path, "Model")

		--local mapId = tostring(logicMgr.MapManager.getMapId());
    	--local mapName = logicMgr.MapManager.getBattleMapName();
    	resMgr:UpdateResTime("Prefabs/MapPref/" .. mapName, "Map")

        HelperFunc.UnloadBattleRes()
    end
    ------------------------------------------------

	--加载资源
	--地图

	local tab_role = {};
	--[[
	for k,v in pairs(tab_Hero) do
		if indexofTable(tab_role,v["partnerModelId"]) <= 0 then
			table.insert(tab_role,v["partnerModelId"]);
		end
	end
	]]

	--[[if battleMapCfg ~= nil then
		local monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId1"]);
		for i=1,#monsterIds do
			if indexofTable(tab_role,monsterIds[i]) <= 0 then
				table.insert(tab_role,monsterIds[i]);
			end
		end
		monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId2"]);
		for i=1,#monsterIds do
			if indexofTable(tab_role,monsterIds[i]) <= 0 then
				table.insert(tab_role,monsterIds[i]);
			end
		end
		monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId3"]);
		for i=1,#monsterIds do
			if indexofTable(tab_role,monsterIds[i]) <= 0 then
				table.insert(tab_role,monsterIds[i]);
			end
		end
	else
		logError("找不到地图数据t_battlemap ，id:  "..mapId)
	end

	local tab_skill = {};
	for i=1,#tab_role do
		local heroCfg = G.dataTable["t_hero"][tostring(tab_role[i])];
		if heroCfg ~= nil then
			local modefile = heroCfg.f_HeroModel;
			local roleCfg = G.dataTable["t_roleconfig"][tostring(modefile)];
			if roleCfg ~= nil then
				local skills = roleCfg["nomalSkill"]--decodeJsonStrToTabel(roleCfg["nomalSkill"]);
				for i=1,#skills do
					if indexofTable(tab_skill,skills[i]) <= 0 then
						table.insert(tab_skill,skills[i]);
					end
				end
			end
		end
	end]]

	resList = {};
	if mapName == nil then
		mapName = 'AutoFightMap29';
	end
	local mapInstance = BattleSceneCacheResouce:GetMapInstance()
	if mapInstance and mapInstance.name == mapName.."(Clone)" then
		mapInstance.transform:SetParent(battleMainRoot.transform,false)
	else
		--table.insert(resList,"Prefabs/MapPref/"..mapName.."#Map");
		destroy(mapInstance)
		BattleSceneCacheResouce:SaveMapInstance(nil)
	end

	if BattleScene.isShow then
		--[[for i=1,#tab_role do
			local heroCfg = G.dataTable["t_hero"][tostring(tab_role[i])];
			if heroCfg ~= nil then
				local modefile = heroCfg.f_HeroModel;
				local path = logicMgr.HeroManager.GetHeroDrawingRolePath(tab_role[i]);
				if modefile ~= nil and modefile ~= "" and indexofTable(resList,path.."#Model") < 1 then
					table.insert(resList,path.."#Model");
				end
			end
		end
		for i=1,#tab_skill do
			local skillShow = G.dataTable["t_skillshow"][tostring(tab_skill[i])];
			if skillShow ~= nil then
				--local preeffect = skillShow.f_SkillFResource;
				--if preeffect ~= nil and preeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preeffect.."#Effect") < 1 then
				--	table.insert(resList,"Prefabs/Skill/"..preeffect.."#Effect");
				--end

				local preeffectList = skillShow.f_SkillFResource;
				--local preeffectList = string.split(preeffectRaw,",");
				local preeffect = preeffectList[1];
				if preeffect ~= nil and preeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preeffect.."#Effect") < 1 then
					table.insert(resList,"Prefabs/Skill/"..preeffect.."#Effect");
				end

				if #preeffectList > 1 then
					preeffect = preeffectList[2];
					if preeffect ~= nil and preeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preeffect.."#Effect") < 1 then
						table.insert(resList,"Prefabs/Skill/"..preeffect.."#Effect");
					end
				end


				local flyeffect = skillShow.f_FlyFResource;
				if flyeffect ~= nil and flyeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..flyeffect.."#Effect") < 1 then
					table.insert(resList,"Prefabs/Skill/"..flyeffect.."#Effect");
				end
				local hiteffect = skillShow.f_HitFResource;
				if hiteffect ~= nil and hiteffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..hiteffect.."#Effect") < 1 then
					table.insert(resList,"Prefabs/Skill/"..hiteffect.."#Effect");
				end
				local preendeffect = skillShow.f_SkillBResource;
				if preendeffect ~= nil and preendeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preendeffect.."#Effect") < 1 then
					table.insert(resList,"Prefabs/Skill/"..preendeffect.."#Effect");
				end
			end
		end]]

		

		local index = 1;
		SpineEffectManager.clearAllEff();
		EffectManager.clearAllEff();
		BattleSceneCacheResouce:ClearCacheRes()
		coroutine.start(this.loadResCoroutine, resList, index, function()
			--this.createPlayer();
			if mapName ~= nil then
				local loadedObj = battleMainRoot.transform:Find(mapName.."(Clone)")
				if loadedObj then 
					this.LoadMapPrefabHelper(loadedObj.gameObject,successFunc)
				else
					resMgr:LoadMapPrefab("Prefabs/MapPref/"..mapName, function(map)
						local obj = newObject(map);
						this.LoadMapPrefabHelper(obj, successFunc)
					end);
				end
			end
		end);
	else
		if mapName ~= nil then
			local loadedObj = battleMainRoot.transform:Find(mapName.."(Clone)")
			if loadedObj then 
				this.LoadMapPrefabHelper(loadedObj.gameObject,successFunc)
			else
				resMgr:LoadMapPrefab("Prefabs/MapPref/"..mapName, function(map)
					local obj = newObject(map);
					this.LoadMapPrefabHelper(obj, successFunc)
				end);
			end
		end
	end
end

function BattleScene.LoadMapPrefabHelper(obj,successFunc)
	mapInstanse = obj
	mapInstanse.gameObject:SetActive(true)
	mapInstanse.transform:SetParent(battleMainRoot.transform);
	Util.Lua_SetLocalPositionXYZ(mapInstanse, 0, 0, 0);
	Util.Lua_SetLocalRotationXYZ(mapInstanse, 0, 0, 0);
	Util.Lua_SetLocalScaleXYZ(mapInstanse, 1, 1, 1)
	if MapLinkCtr ~= nil then
		MapLinkCtr.init(mapInstanse, cameraMain);
	end

	if successFunc~=nil then
		successFunc();
	end
end

function BattleScene.AddBgLayer()
	if bgComponent == nil then 
		bgComponent = UIComponentScrollRectEx.New()
	end
	local show = BattleSceneCacheResouce:InitMapInstance(mapInstanse,false)
	bgComponent:InitLayerOhters(cameraMain,show,true)
	bgComponent:OnComEnable()
end

function BattleScene.destroyScene()
	--log('BattleScene.destroyScene')
	BattleSceneCacheResouce:SaveMapInstance(BattleSceneCacheResouce:GetMapInstance())
	if mapInstanse ~= nil then
		MapLinkCtr.Destroy();
		--destroy(mapInstanse);
		mapInstanse = nil;
	end
	this.pause()
	for i =1,#tab_HeroList do
		local hero = tab_HeroList[i];
		hero:destroy();
	end

	for i =1,#tab_MonsterList do
		local monster = tab_MonsterList[i];
		monster:destroy();
	end

	if tab_HeroList then
		table.clear(tab_HeroList)
	end
	if bgComponent then bgComponent:Destroy() end
	bgComponent = nil;
	tab_HeroList = {};
	tab_MonsterList = {};
	SpineEffectManager.clearAllEff();
	EffectManager.clearAllEff();
	battleMainRoot = panelMgr.BattleMain;
	if battleMainRoot ~= nil then

		local count = battleMainRoot.transform.childCount;
		if count > 0 then
			for i=0,count-1 do
				local child = battleMainRoot.transform:GetChild(i);
				if not BattleSceneCacheResouce:IsCacheObj(child.gameObject) then
					destroy(child.gameObject);
				end
			end
		end

	end

	this.DelEnterSceneTimer()
	if skeletonAnimStateUserDataString then 
		table.clear(skeletonAnimStateUserDataString)
	end
end

function BattleScene.loadResCoroutine(res,index,callback)
    if(index <= #res) then
        loadResource(res[index], function (prefabobj)
            local array = string.split(res[index], "#");
            if #array > 1 then
                local type = array[2];
				if type == "Effect" then
					-- print("------------>array:", table.tostring(array) ) -- array:	{[1] = "Prefabs/Skill/fxh202f",[2] = "Effect",}
					local obj_name = nil
                	local ret = string.match(array[1], "/[^/]*[^/]$")
                	if ret ~= nil then
                	    obj_name = string.gsub(ret, "/", "")
                	end
					SpineEffectManager.createEffectPool(battleMainRoot.transform, prefabobj, 1, obj_name)
				elseif type == "Model" then
                    --resMgr:LoadModelPrefab(array[1],function() end)
				elseif type == "Map" then
                    --resMgr:LoadMapPrefab(array[1],function(map) end)
				end
            end
            index = index + 1;    
            coroutine.start(this.loadResCoroutine, res, index, callback)
        end);
	else
        if callback ~= nil then
            callback();
        end
    end
end

function BattleScene.changeState(state)
	if state == EnumConst.BattleSceneStateEnum.ENTERSCENE then
		local pos = decodeJsonStrToTabel(battleMapCfg["f_CameraPos1"]);
		Util.Lua_SetLocalPositionXYZ(cameraMain,pos[1],pos[2],-18);
		if mapInstanse~=nil then
			MapLinkCtr.reset();
		end
		this.enterScene();
		if BattleScene.isShow then
			local monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId1"]);
			this.createMonster(monsterIds);
		end
	elseif state == EnumConst.BattleSceneStateEnum.BATTLETIME1 then
	elseif state == EnumConst.BattleSceneStateEnum.MOVETIME1 then
		local monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId2"]);
		local heroEndPos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos2"]);
		this.createMonster(monsterIds);
		for i=1,#tab_HeroList do
			local hero = tab_HeroList[i];
			local r = hero.roleObj.transform;
			local pos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos2"]);
			if pos[i] then 
				local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(r,0,0,0);
				local targetPos = Vector3(pos[i][1],posy,pos[i][2]);
				hero:setRunPos(targetPos);
			end
		end

		local posx,posy,posz = Util.Lua_GetPositionXYZ(cameraMain.transform,0,0,0);
		local cameraPos = decodeJsonStrToTabel(battleMapCfg["f_CameraPos2"]);
		local battlePosx = Util.Lua_GetPositionXYZ(battleMainRoot.transform,0,0,0);
		local offsetTime = Mathf.Abs(posx - battlePosx - cameraPos[1])/tab_HeroList[1].speedRun;
		cameraMain.transform:DOMove(Vector3(battlePosx + cameraPos[1],cameraPos[2],posz),offsetTime * 0.5,false);

	elseif state == EnumConst.BattleSceneStateEnum.BATTLETIME2 then
	elseif state == EnumConst.BattleSceneStateEnum.MOVETIME2 then
		local monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId3"]);
		local heroEndPos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos3"]);
		this.createMonster(monsterIds);
		for i=1,#tab_HeroList do
			local hero = tab_HeroList[i];
			local r = hero.roleObj.transform;
			local pos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos3"]);
			if pos[i] then 
				local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(r,0,0,0);
				local targetPos = Vector3(pos[i][1],posy,pos[i][2]);
				hero:setRunPos(targetPos);
			end
		end

		local posx,posy,posz = Util.Lua_GetPositionXYZ(cameraMain,0,0,0)
		local cameraPos = decodeJsonStrToTabel(battleMapCfg["f_CameraPos3"]);
		local battlePosx = Util.Lua_GetPositionXYZ(battleMainRoot.transform,0,0,0);
		local offsetTime = Mathf.Abs(posx - battlePosx - cameraPos[1])/tab_HeroList[1].speedRun;
		cameraMain.transform:DOMove(Vector3(battlePosx + cameraPos[1],cameraPos[2],posz),offsetTime * 0.5,false);
	elseif state == EnumConst.BattleSceneStateEnum.BATTLETIME3 then
	elseif state == EnumConst.BattleSceneStateEnum.LEAVESCENE then
		this.leaveScene();
		FireEvent(Config.EventType.Fight_Show_Shadow);
	else
		local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(cameraMain,0,0,0)
		local newPos = decodeJsonStrToTabel(battleMapCfg["f_CameraPos1"]);
		Util.Lua_SetLocalPositionXYZ(cameraMain,newPos[1],newPos[2],posz);
	end
	battleState = state;
end

function BattleScene.enterScene()
	stateIndex = 1
	this.isFirstEnterScene = true
	-- 需等待角色加载成功
	this.DelEnterSceneTimer()
	this.enterSceneTimer = utimer.frameCall(function()
		local isAllLoad = true
		for key, value in pairs(tab_HeroList) do
			if value.roleObj == nil then 
				isAllLoad = false
			end
		end
		if isAllLoad then 
			this.DelEnterSceneTimer()
			for i=1,#tab_HeroList do
				local hero = tab_HeroList[i];
				if hero ~= nil and hero.roleObj ~= nil then
					local r = hero.roleObj.transform;
					hero:init();
					local reborn = decodeJsonStrToTabel(battleMapCfg["f_RebornPos"]);
					local pos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos1"]);
					if reborn == nil then
						logError("配置表t_battlemap找不到f_RebornPos  stageId:"..mapId)
					else
						if  reborn[i] and pos[i] then
							local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(r,0,0,0);
							local beginPos = Vector3(reborn[i][1],posy,reborn[i][2]);
							local targetPos = Vector3(pos[i][1],posy,pos[i][2]);
							--hero:setPosition(beginPos);
							hero:setPosition(targetPos); --直接战斗
							--hero:setRunPos(targetPos);
							hero:setActive(true);
						end
					end

				end
			end
		end
	end,-1)
end

function BattleScene.DelEnterSceneTimer()
	if this.enterSceneTimer then 
		utimer.remove(this.enterSceneTimer)
		this.enterSceneTimer = nil
	end
end

function BattleScene.leaveScene()
	for i=1,#tab_HeroList do
		local hero = tab_HeroList[i];
        local r = hero.roleObj.transform;
		local pos = decodeJsonStrToTabel(battleMapCfg["f_EndPos"]);
		local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(r,0,0,0);
		local targetPos = Vector3(pos[i][1],posy,pos[i][2]);
		hero:setRunPos(targetPos);
	end
end

function BattleScene.createPlayer()
	for i =1,#tab_HeroList do
		local hero = tab_HeroList[i]
		hero:destroy()
		hero = nil
	end
	tab_HeroList = {}

	local i = 1
	local formation = logicMgr.FormationManager.GetFormation(EnumConst.FormationType.Duplicate, true)
	--[[ 注释无效代码, 多队副本阵容可能为空,和后端确认后这里就先不用多队阵容]]
	-- local teamNum = logicMgr.MapManager.getStageNeedTeamNum(logicMgr.MapManager.getMapId())
	-- if teamNum > 1 then
	-- 	formation = logicMgr.FormationManager.GetFormation(EnumConst.FormationType.DuplicateMore)
	-- 	-- local num = math.random(1, teamNum)
	-- 	-- 如果没有多队,就重新取单队
	-- 	if type(formation[num]) == "table" then
	-- 		formation = formation[num]
	-- 	else
	-- 		formation = logicMgr.FormationManager.GetFormation(EnumConst.FormationType.Duplicate, true)
	-- 	end
	-- end
    if formation ~= nil then
		for k,v in pairs(formation) do
			local partnerId = tostring(v)
			if toNumber(partnerId) > 0 and #tab_HeroList < uPheroMax then
				local heroData = logicMgr.HeroManager.getHeroDatabyPartnerId(partnerId,true)
				local roleInfo = EntityInfo:new()
				roleInfo.fighterId = 1000 + i
				roleInfo.partnerId = heroData["partnerId"]
				roleInfo.partnerModelId = heroData["partnerModelId"]
				roleInfo.robot = false
				roleInfo.monster = false
				roleInfo.name = heroData.name
				roleInfo.level = heroData["level"]
				roleInfo.star = heroData["star"]
				roleInfo.teamIndex = 1
				local hero = this.createFighter(roleInfo)
				table.insert(tab_HeroList,hero)
				fighterMap[roleInfo.fighterId] = hero
				i = i + 1
			end
        end
    end
end

function BattleScene.createMonster(monsterIds)
	for i =1,#tab_MonsterList do
		local monster = tab_MonsterList[i]
		monster:destroy()
		monster = nil
	end
	tab_MonsterList = {}
    if monsterIds ~= nil and next(monsterIds) ~= nil then
		for i = 1, #monsterIds do
			local monsterCfg = G.dataTable["t_hero"][tostring(monsterIds[i])];
			local roleInfo = EntityInfo:new()
			roleInfo.fighterId = i
			roleInfo.partnerId = i
			roleInfo.partnerModelId = tonumber(monsterIds[i])
			roleInfo.robot = true
			roleInfo.monster = false
			roleInfo.name = monsterCfg.name
			roleInfo.teamIndex = 2
			roleInfo.hp = 500
			roleInfo.maxHP = 500
			local monster = this.createFighter(roleInfo)
			local roleCfg = G.dataTable["t_roleconfig"][tostring(monsterCfg.f_HeroModel)]
			if roleCfg ~= nil then
				local skills = roleCfg.nomalSkill
				monster.normalSkill = {}
				for i=1,#skills do
					if indexofTable(monster.normalSkill,skills[i]) <= 0 then
						table.insert(monster.normalSkill,skills[i])
					end
				end
			end 
			table.insert(tab_MonsterList, monster)
			fighterMap[roleInfo.fighterId] = monster
		end
	else
		logError("怪物组ids为空")
	end
	-- 缓存起来供下一次使用
	for key, value in pairs(tab_MonsterList) do 
		if  value.roleObj ~= nil then
			local path = logicMgr.HeroManager.GetHeroDrawingRolePath(value.partnerModelId)
			BattleSceneCacheResouce:AddReUseObj(path, value.roleObj)
		end
	end
end

function BattleScene.createFighter(fightInfo)
	local roleFighter = Entity:new(fightInfo);
	logicMgr.HeroManager.processHeroBaseAttr(roleFighter,roleFighter.level,roleFighter.star);
	logicMgr.HeroManager.processHeroAllAttr(roleFighter);

	--FighterAttributeManager.initFighterAttribute(roleFighter);
	roleFighter.scale = Vector3(0.8,0.8,0.8);
	roleFighter:initAvatar(battleMainRoot.transform,function()
		if fightInfo.position ~= nil then
			roleFighter:setPosition(Vector3(fightInfo.position.x,0,fightInfo.position.y));
		else
			roleFighter:setPosition(Vector3(0,0,0));
		end
		roleFighter:init();
		roleFighter:setActive(false);
	end);
    return roleFighter;
end

function BattleScene.onUpdate()
	if not BattleScene.isShow then
		return
	end
	local typeIndex = (stateIndex-1) % 2						-- 状态类型 0移动/1战斗
	local realIndex = (math.ceil(stateIndex / 2) - 1) % 3 + 1	-- 循环索引 1 2 3 -> 1 2 3
	if typeIndex == 0 then 
		for i =1,#tab_HeroList do
			local hero = tab_HeroList[i];
			hero:onUpdate(fightTimer.duration);
		end
		local allFinish = true;
		for i =1,#tab_HeroList do
			local hero = tab_HeroList[i];
			if hero:getModel() == nil or hero:getAniState() ~= Config.AnimationState.IDLE then
				allFinish = false;
				break;
			end
		end
		if allFinish then
			local distanceIndex = math.floor(stateIndex / 6)
			local addDistance = distanceIndex * MapLinkCtr.GetDistance()
			for i=1,#tab_MonsterList do
				local monster = tab_MonsterList[i];
				if not monster.roleObj then
					printError("monster.roleObj and break")
					break ;
				end
				local r = monster.roleObj.transform;
				monster:init();
				local pos = decodeJsonStrToTabel(battleMapCfg["f_MonsterPos"..realIndex]);
				local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(r,0,0,0);
				local targetPos = Vector3(pos[i][1],posy,pos[i][2]);
				targetPos.x = targetPos.x + addDistance
				monster:setPosition(targetPos);
				monster:setActive(true);
			end
			if this.isFirstEnterScene then
				this.StartFightImmediate()
				this.isFirstEnterScene = false
			else
				FireEvent(Config.EventType.Fight_Run,false)
			end
			stateIndex = stateIndex + 1
		end
	else
		this.updateBattle();
		if #tab_MonsterList <= 0 then
			-- 跑向下一个点
			local realIndex = realIndex + 1
			if realIndex > 3 then realIndex = 1 end
			local distanceIndex = math.floor((stateIndex+1) / 6)
			local addDistance = distanceIndex * MapLinkCtr.GetDistance()
			local monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId"..realIndex]);
			local heroEndPos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos"..realIndex]);
			this.createMonster(monsterIds);
			for i=1,#tab_HeroList do
				local hero = tab_HeroList[i];
				local r = hero.roleObj.transform;
				local pos = decodeJsonStrToTabel(battleMapCfg["f_HeroPos"..realIndex]);
				if pos[i] then 
					local posx,posy,posz = Util.Lua_GetLocalPositionXYZ(r,0,0,0);
					local targetPos = Vector3(pos[i][1],posy,pos[i][2]);
					targetPos.x = targetPos.x + addDistance
					hero:setRunPos(targetPos);
				end
			end

			local posx,posy,posz = Util.Lua_GetPositionXYZ(cameraMain.transform,0,0,0);
			local cameraPos = decodeJsonStrToTabel(battleMapCfg["f_CameraPos"..realIndex]);
			local battlePosx = Util.Lua_GetPositionXYZ(battleMainRoot.transform,0,0,0);
			local targetPosX = battlePosx + cameraPos[1] + addDistance
			local offsetTime = Mathf.Abs(posx - targetPosX)/tab_HeroList[1].speedRun;
			cameraMain.transform:DOMove(Vector3(targetPosX,cameraPos[2],posz),offsetTime * 0.5,false);

			stateIndex = stateIndex + 1
			FireEvent(Config.EventType.Fight_Run,true)
		end
	end

	--更新 entity effect
	for i =1,#tab_HeroList do
		local hero = tab_HeroList[i];
		hero:updateEffect(fightTimer.duration);
	end
	for i =1,#tab_MonsterList do
		local monster = tab_MonsterList[i];
		monster:updateEffect(fightTimer.duration);
	end
end
---@param entity Entity
---@param targetList Entity[]
---@return Entity
function BattleScene.GetNearTarget(entity,targetList)
	if entity == nil then return nil end
	local minDistance = 1000000;
	local target
	for k,v in pairs(targetList) do
		if v ~= nil and v:getModel() ~= nil and not v:getDeadState() and entity:getModel() ~= nil then
			local distance = Vector3.SqrDistance(entity:getPosition(), v:getPosition());
			if minDistance > distance then
				target = v;
				minDistance = distance;
			end
		end
	end
	return target
end
---@param entity Entity
---@param target Entity
---@param skillData table t_skill表
---@param isHalfShape boolean 是否人物身形减半
function BattleScene.IsInSkillRange(entity,target,skillData,isHalfShape)
	local circleLimit = decodeJsonStrToTabel(Entity:GetTableValue(skillData,"f_CircleRangeLimit"));
	local rangeLimit = decodeJsonStrToTabel(Entity:GetTableValue(skillData,"f_RangeLimit"));
	local skillRange = 0;
	if circleLimit ~= nil and circleLimit ~= "" and circleLimit > 0 then
		skillRange = toNumber(circleLimit/EnumConst.TEN_THOUSANDTH);
	elseif rangeLimit ~= nil and rangeLimit ~= "" then
		skillRange = toNumber(rangeLimit[1]/2);
	end
	local range = skillRange + (isHalfShape and target.shape.x/2 or target.shape.x)
	local dis = Vector3.SqrDistance(entity:getPosition(),target:getPosition())
	if dis < range*range then
		return true
	else
		return false
	end

end

function BattleScene.StartFightImmediate()
	local cycleCount = 0
	while(cycleCount < 60) do
		cycleCount = cycleCount + 1
		local count = 0
		for i =1,#tab_HeroList do
			local hero = tab_HeroList[i];
			local target = this.GetNearTarget(hero,tab_MonsterList)
			if target ~= nil and hero:getAttack() then
				local skillId,skillData,skillShow = this.selectedSkill(hero);
				if not skillData or this.IsInSkillRange(hero,target,skillData) then --无技能就结束，避免死循环
					hero:setAttackTarget(target)
					count = count + 1
				else
					local hp = hero:getPosition()
					local tp = target:getPosition()
					local dir = Vector3.GetCacheVec():SetV(tp):Sub(hp):SetNormalize()--Vector3.Normalize(tp - hp)
					dir:Mul(hero.speedRun * 0.05)
					dir:Add(hp)
					hero:setPosition(dir)
					Vector3.ReturnToPool(dir)
				end
			end
		end
		for i =1,#tab_MonsterList do
			local monster = tab_MonsterList[i];
			local target = this.GetNearTarget(monster,tab_HeroList)
			if target ~= nil and monster:getAttack() then
				local skillId,skillData,skillShow = this.selectedSkill(monster);
				if not skillData or this.IsInSkillRange(monster,target,skillData) then --无技能就结束，避免死循环
					monster:setAttackTarget(target)
					count = count + 1
				else
					local hp = monster:getPosition()
					local tp = target:getPosition()
					local dir = Vector3.GetCacheVec():SetV(tp):Sub(hp):SetNormalize()--Vector3.Normalize(tp - hp)
					dir:Mul(monster.speedRun * 0.05)
					dir:Add(hp)
					monster:setPosition(dir)
					Vector3.ReturnToPool(dir)
				end
			end
		end
		if count == #tab_HeroList+#tab_MonsterList then
			break
		end
	end

end
function BattleScene.updateBattle()
	--索敌
	for i =1,#tab_HeroList do
		local hero = tab_HeroList[i];
		if not hero:getDeadState() then
			if hero:getTarget() == nil then
				--local heroCfig = G.dataTable["t_hero"][tostring(hero:getModelId())];
				--local minDistance = 10000;
				local target = this.GetNearTarget(hero,tab_MonsterList);
				if target ~= nil and hero:getAttack() then
					if target:getDeadState() then
						hero:setAttackTarget(nil);
						break;
					end

					local skillId,skillData,skillShow = this.selectedSkill(hero);
					if this.IsInSkillRange(hero,target,skillData) then
						hero:setAttackTarget(target);
						local x,y,z = Util.Lua_GetLocalPositionXYZ(hero:getModel(),0,0,0);
						hero:setRunPos(Vector3(x,y,z));
						this.doAttack(hero,target,skillData,skillShow);
					else
						hero:setRunTarget(target);
					end
				end
			else
				local target = hero:getTarget();
				if target:getDeadState() then
					hero:setAttackTarget(nil);
				end
				if hero:getAttack() and not target:getDeadState() then
					local skillId,skillData,skillShow = this.selectedSkill(hero);
					if this.IsInSkillRange(hero,target,skillData) then
						local x,y,z = Util.Lua_GetLocalPositionXYZ(hero:getModel(),0,0,0);
						hero:setRunPos(Vector3(x,y,z));
						this.doAttack(hero,target,skillData,skillShow);
					else
						hero:setRunTarget(target);
					end
				end
			end
		end
	end
	for i =1,#tab_MonsterList do
		local monster = tab_MonsterList[i];
		if not monster:getDeadState() then
			if monster:getTarget() == nil then
				--local monsterCfig = G.dataTable["t_monster"][tostring(monster:getModelId())];
				--local minDistance = 10000;
				local target = this.GetNearTarget(monster,tab_HeroList);
				if target ~= nil and monster:getAttack() then
					local skillId,skillData,skillShow = this.selectedSkill(monster);
					if this.IsInSkillRange(monster,target,skillData,true) then
						monster:setAttackTarget(target);
						local x,y,z = Util.Lua_GetLocalPositionXYZ(monster:getModel(),0,0,0);
						monster:setRunPos(Vector3(x,y,z));
						this.doAttack(monster,target,skillData,skillShow)
					else
						monster:setRunTarget(target);
					end
				end
			else
				local target = monster:getTarget();
				if target:getDeadState() then
					monster:setAttackTarget(nil);
				end
				if monster:getAttack() and not target:getDeadState() then
					local skillId,skillData,skillShow = this.selectedSkill(monster);
					if this.IsInSkillRange(monster,target,skillData,true) then
						local x,y,z = Util.Lua_GetLocalPositionXYZ(monster:getModel(),0,0,0);
						monster:setRunPos(Vector3(x,y,z));
						this.doAttack(monster,target,skillData,skillShow)
					else
						monster:setRunTarget(target);
					end
				end
			end
		end
	end
	
	--检查死亡
	for i =1,#tab_MonsterList do
		local monster = tab_MonsterList[i];
		if monster.hp <= 0 then
			monster:setDead();
		end
		if monster:getDead() then
			monster:destroy();
			table.remove(tab_MonsterList, i);
			break;
		end
	end

	--更新
	for i =1,#tab_HeroList do
		local hero = tab_HeroList[i];
		hero:onUpdate(fightTimer.duration);
	end
	for i =1,#tab_MonsterList do
		local monster = tab_MonsterList[i];
		monster:onUpdate(fightTimer.duration);
	end
end

function BattleScene.selectedSkill(hero)
	local skillId = hero.normalSkill[Util.RandomInt(1,#hero.normalSkill)];
	local skillData = G.dataTable["t_skill"][tostring(skillId)];
	local skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
	return skillId,skillData,skillShow; 
end

--攻击
function BattleScene.doAttack(fighter,target,skillData,skillShow)
	if skillShow and skillShow.f_SkillShowType ~= nil and skillShow.f_SkillShowType ~= "" and skillData ~= nil then
        local showType = toNumber(skillShow.f_SkillShowType);
        local attackShowDuration = toNumber(skillData.f_GuideTime);
        local attackMoveSpeed = toNumber(skillData.f_Speed);
        local flip = getRoleFlip(fighter,target);
        fighter:setFlip(flip);
        if showType == EnumConst.AttackShowType.MOVE then
            local value = {};
            value.attackShowDuration = attackShowDuration/EnumConst.THOUSANDTH;
            value.attackMoveSpeed = attackMoveSpeed/EnumConst.TEN_THOUSANDTH;
            if flip then
                value.attackDirection = Vector3(-1,0,0); 
            else
                value.attackDirection = Vector3(1,0,0); 
            end
            fighter:setAttackShowType(showType,value);
        elseif showType == EnumConst.AttackShowType.SPRINT then
        elseif showType == EnumConst.AttackShowType.TARGETEFFECT then
        else
            fighter:setAttackShowType(EnumConst.AttackShowType.NONE,nil);
        end 

        --释放技能特效
        local effFObj,effBObj = nil;
        if showType == EnumConst.AttackShowType.TARGETEFFECT then
            effFObj,effBObj = Entity:playSkill(target,skillShow,flip,0.6);
        else
            effFObj,effBObj = Entity:playSkill(fighter,skillShow,flip,0.8);
        end
        
        --场景特效
        local effFCenterObj,effBCenterObj = Entity:playCenter(fighter,skillShow);
    
        if effFObj ~= nil and effFObj.effGo ~= nil then
            this.addSkeletonEvent(effFObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
        end
        if effBObj ~= nil and effBObj.effGo ~= nil then
            this.addSkeletonEvent(effBObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
        end
        if effFCenterObj ~= nil and effFCenterObj.effGo ~= nil then
            this.addSkeletonEvent(effFCenterObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
        end
        if effBCenterObj ~= nil and effBCenterObj.effGo ~= nil then
            this.addSkeletonEvent(effBCenterObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
        end
        this.addSkeletonEvent(fighter:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
		fighter:playSkillAction(skillShow);
		fighter.canAttack = false;
		-- Util.WaitForSeconds(function ()
		-- 	fighter.canAttack = true;
		-- end, tonumber(attackShowDuration/1000));
		utimer.delayCall(function()
			fighter.canAttack = true;
        end, tonumber(attackShowDuration))

        local bulletTime = toNumber(skillData.f_BulletTime);
        local guideTime = toNumber(skillData.f_GuideTime);
        this.cutInSkillTime = guideTime/EnumConst.THOUSANDTH;
        if bulletTime > 0 and fighter.teamIndex == 1 then
            this.cutInState  = true;
            this.cutInTime = bulletTime/EnumConst.THOUSANDTH;
            for i=1,#this.fighterList do
                local _fighter = this.fighterList[i];
                --if not FighterManager.isDie(fighters[i]) and fighter.fighterId ~= fighters[i].fighterId then
                _fighter:PauseCurrentAction();
				_fighter:PauseEffect();
                --end
                if fighter.fighterId == _fighter.fighterId then
                    fighter:playFullScreen(skillShow);
                    fighter:playCutIn(skillShow);
                    fighter:setOrder(Config.SortingDefault.Role);
                    target:setOrder(Config.SortingDefault.Role);
                end
            end
        end

        if skillData.f_SkillBySkill ~= nil and skillData.f_SkillBySkill ~= "" then
            local nextSkills = skillShow.f_NextSkill--decodeJsonStrToTabel(skillShow.f_NextSkill);
			nextSkills = skillData.f_SkillBySkill;
            if nextSkills ~= nil and #nextSkills > 0 then
                for i=1,#nextSkills do
                    local nextSkillId = nextSkills[i][2];
                    local nextSkillDelay = nextSkills[i][1];
                    
                    -- Util.WaitForSeconds(function ()
                    --     local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)];
                    --     local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)];
                    --     if nextSkillShow.f_FlyFResource ~= nil and nextSkillShow.f_FlyFResource ~= "" and nextSkillShow.f_FlyFName ~= nil and nextSkillShow.f_FlyFName ~= "" then
                    --         BattleScene.doFly(fighter,target,nextSkillData,nextSkillShow);
                    --     else
                    --         BattleScene.doAttack(fighter,target,nextSkillData,nextSkillShow);
                    --     end
                    -- end,nextSkillDelay/EnumConst.THOUSANDTH);

                    utimer.delayCall(function()
                        local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)];
                        local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)];
                        if nextSkillShow.f_FlyFResource ~= nil and nextSkillShow.f_FlyFResource ~= "" and nextSkillShow.f_FlyFName ~= nil and nextSkillShow.f_FlyFName ~= "" then
                            BattleScene.doFly(fighter,target,nextSkillData,nextSkillShow);
                        else
                            BattleScene.doAttack(fighter,target,nextSkillData,nextSkillShow);
                        end
        			end, nextSkillDelay )
                end
            end 
        end 
    end
end

function UserDataEventDelegate2(e, userdata)
    local time = e.Time; 
    local skillId = toNumber(userdata.Name);
    local fighterId = userdata.Int;
    local targetId = Mathf.Floor(userdata.Float);
    local skillShow = skeletonAnimStateUserDataString[skillId]
    if e.Int == EnumConst.SpineEventType.HIT then
        local fighter = fighterMap[fighterId];
        local target = fighterMap[targetId];
        local skillBean = G.dataTable["t_skill"][tostring(skillId)];
        if skillShow == nil then
            skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
        end

		--Util.LogError('doHit   '..tostring(fighterId)..'   '..tostring(targetId)..'    '..tostring(target));
		if target ~= nil then
			this.doHit(fighter,target,skillBean,skillShow);
		end
    elseif e.Int == EnumConst.SpineEventType.DAMAGE then
		local target = fighterMap[targetId];
		if target ~= nil and target.teamIndex ~= 1 then
			target:damage(1,100 + Util.RandomInt(1,20),false);
		end
    elseif e.Int == EnumConst.SpineEventType.CAMERA then
		local target = fighterMap[targetId];
		if target ~= nil then
			target:ShakeCamera(1,200);
		end
    end
end

function BattleScene.addSkeletonEvent(skeleton,fighterId,targetId,skillId,skillShow)
    if skeleton ~= nil then
        local skeletonAnim = skeleton:GetComponent("SkeletonAnimation");
        if skeletonAnim ~= nil and skeletonAnim.state ~= nil then
   			-- skeletonAnim.state.UserData = Spine.EventData.New(tostring(skillId));
   			-- skeletonAnim.state.UserData.Int = fighterId;
   			-- skeletonAnim.state.UserData.Float = targetId;
   			-- skeletonAnim.state.UserData.String = "";
			skeletonAnim:SetAnimationStateEventData(tostring(skillId), tonumber(fighterId), tonumber(targetId) ) --string event_name, int int_data, float float_data, string string_data = null
			
			skeletonAnimStateUserDataString[skillId] = skillShow
            -- skeletonAnim.state.UserEvent = skeletonAnim.state.UserEvent - UserDataEventDelegate2;
            -- skeletonAnim.state.UserEvent = skeletonAnim.state.UserEvent + UserDataEventDelegate2;
            skeletonAnim:RegisterStateLuaUserFunction(UserDataEventDelegate2)
        end
    end 
end

--受击
function BattleScene.doHit(fighter,target,skillBean,skillShow)
	if fighter == nil then 
		return
	end
	if target:getDeadState() then
		return;
	end
    if skillShow.f_HitShowType ~= nil and skillShow.f_HitShowType ~= "" then
        local flip = getRoleFlip(fighter,target);
        local showType = toNumber(skillShow.f_HitShowType);
        local hitValue = skillShow.f_HitShowValue or {} --decodeJsonStrToTabel(skillShow.f_HitShowValue);
        if showType == EnumConst.HitShowType.REPULSE then
            local speed = toNumber(hitValue[2]);
            local time = toNumber(hitValue[1]);
            if time == 0 then
                time = EnumConst.FIGHT_FRAME;
            end
            local value = {};
            value.hitShowDuration = time/EnumConst.THOUSANDTH;
			value.maxHitShowDuration = value.hitShowDuration;
            value.hitMoveSpeed = speed/EnumConst.TEN_THOUSANDTH/value.hitShowDuration;
            if flip then
                value.hitDirection = Vector3(-1,0,0); 
            else
                value.hitDirection = Vector3(1,0,0); 
            end
            target:setHitShowType(showType,value);
        elseif showType == EnumConst.HitShowType.HITFLY then
            --local time = toNumber(hitValue[1]);
            --if time == 0 then
            --    time = EnumConst.FIGHT_FRAME;
            --end
            --local speed = toNumber(hitValue[2]);
            --local speed2 = toNumber(hitValue[3]);
			--
            --local value = {};
            --value.hitShowDuration = time/EnumConst.THOUSANDTH;
            --value.hitMoveSpeed = speed/EnumConst.TEN_THOUSANDTH;
            --target:setHitShowType(showType,value);

			local value = {};
			value.hitShowDuration = 500/EnumConst.THOUSANDTH; --time
			value.maxHitShowDuration = value.hitShowDuration;
			target:setHitShowType(showType,value);
			target:setAniState(Config.AnimationState.HURT,nil,false, true);
			Entity:playHit(target,skillShow,flip);

		elseif showType == EnumConst.HitShowType.HITDOWN then
			--logMy('HITDOWN', target.fighterId, skillShow.f_HitShowType);

			target:setHitShowType(showType);
			target:setAniState(Config.AnimationState.HITFLY,nil,false, true);
			Entity:playHit(target,skillShow,flip);

        else
			target:setAniState(Config.AnimationState.HURT,nil,false);
			Entity:playHit(target,skillShow,flip);
        end

    end
end

function BattleScene.doFly(fighter,target,skillData,skillShow)
	if skillShow.f_SkillShowType ~= nil and skillShow.f_SkillShowType ~= "" and skillData ~= nil then
		if target == nil or fighter == nil or target.roleObj == nil or fighter.roleObj == nil then
			return;
		end

        local showType = toNumber(skillShow.f_SkillShowType);

        local bulletTime = toNumber(skillData.f_BulletTime);
        local guideTime = toNumber(skillData.f_GuideTime);
        this.cutInSkillTime = guideTime/EnumConst.THOUSANDTH;

        if showType == EnumConst.AttackShowType.TARGETEFFECT then
            effFObj,effBObj = Entity:playSkill(target,skillShow,flip); 
            if effFObj ~= nil then
                FightManager.addSkeletonEvent(effFObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
            end
            if effBObj ~= nil then
                FightManager.addSkeletonEvent(effBObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
            end
        elseif showType == EnumConst.AttackShowType.ATTACKEFFECT then
            effFObj,effBObj = Entity:playSkill(fighter,skillShow,flip); 
            if effFObj ~= nil then
                FightManager.addSkeletonEvent(effFObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
            end
            if effBObj ~= nil then
                FightManager.addSkeletonEvent(effBObj:getSkeletonAnimation(),fighter.fighterId,target.fighterId,skillData.f_SkillID,skillShow);
            end
        elseif showType == EnumConst.AttackShowType.CURVE then
            local dtime = 1000/EnumConst.THOUSANDTH;
            if skillShow.f_SkillShowValue ~= nil and skillShow.f_SkillShowValue ~= "" then
                --dtime = toNumber(skillShow.f_SkillShowValue)/EnumConst.THOUSANDTH;

				local showValueTbl = skillShow.f_SkillShowValue or {};
				local showValue = showValueTbl[1] or 0;
				dtime = showValue/EnumConst.THOUSANDTH;
            end
        
            local flip = getRoleFlip(fighter,target);
			local flyStartPos = fighter:getOffsetPosition(skillShow.f_FlyFPosition, flip);
			local hitPos = target:getOffsetPosition(skillShow.f_HitFPosition, flip);

			local flyDir = hitPos - flyStartPos;
			local vSpeed = Vector3.Normalize(flyDir);
			local distance = flyDir.magnitude;
    
            vSpeed = vSpeed * (distance/dtime);

			--Entity:playFly(fighter,skillShow,vSpeed,dtime,fighter_Pos,function()
			Entity:playFly(fighter,skillShow,vSpeed,dtime, flyStartPos,function()
            --Entity:playFly(fighter,skillShow,vSpeed,dtime,fighter_Pos,function()
                local eventData = Spine.EventData.New(tostring(skillShow.f_SkillID));
                eventData.Int = fighter.fighterId;
				eventData.Float = target.fighterId;
				eventData.String = "";
				skeletonAnimStateUserDataString[skillShow.f_SkillID] = skillShow
                local event = Spine.Event.New(0,eventData);
                event.Int = EnumConst.SpineEventType.HIT;
                UserDataEventDelegate2(event,eventData);
                local event2 = Spine.Event.New(0,eventData);
                event2.Int = EnumConst.SpineEventType.DAMAGE;
                UserDataEventDelegate2(event2,eventData);
            end);
        elseif showType == EnumConst.AttackShowType.TriggerHit then
            local eventData = Spine.EventData.New(tostring(skillShow.f_SkillID));
            eventData.Int = fighter.fighterId;
			eventData.Float = target.fighterId;
			eventData.String = "";
			skeletonAnimStateUserDataString[skillShow.f_SkillID] = skillShow
            local event = Spine.Event.New(0,eventData);
            event.Int = EnumConst.SpineEventType.DAMAGE;
            UserDataEventDelegate2(event,eventData);
        elseif showType == EnumConst.AttackShowType.Arrow then
            local speed = toNumber(skillData.f_Speed)/EnumConst.TEN_THOUSANDTH;
            local flip = getRoleFlip(fighter,target);
			local flyStartPos = fighter:getOffsetPosition(skillShow.f_FlyFPosition, flip);
			local hitPos = target:getOffsetPosition(skillShow.f_HitFPosition, flip);
			local flyDir = hitPos - flyStartPos;
			local vSpeed = Vector3.Normalize(flyDir);
			local distance = flyDir.magnitude;
    
            vSpeed = vSpeed * speed;
    
			--Entity:playFly(fighter,skillShow,vSpeed,distance/speed,fighter_Pos,function()
			Entity:playFly(fighter,skillShow,vSpeed,distance/speed, flyStartPos,function()
            --Entity:playFly(fighter,skillShow,vSpeed,distance/speed,fighter_Pos,function()
                local eventData = Spine.EventData.New(tostring(skillShow.f_SkillID));
                eventData.Int = fighter.fighterId;
				eventData.Float = target.fighterId;
				eventData.String = "";
				skeletonAnimStateUserDataString[skillShow.f_SkillID] = skillShow
                local event = Spine.Event.New(0,eventData);
                event.Int = EnumConst.SpineEventType.HIT;
                UserDataEventDelegate2(event,eventData);
                local event2 = Spine.Event.New(0,eventData);
                event2.Int = EnumConst.SpineEventType.DAMAGE;
                UserDataEventDelegate2(event2,eventData);
            end);
        else
            local speed = toNumber(skillData.f_Speed)/EnumConst.TEN_THOUSANDTH;
            local flip = getRoleFlip(fighter,target);

			local flyStartPos = fighter:getOffsetPosition(skillShow.f_FlyFPosition, flip);
			local hitPos = target:getOffsetPosition(skillShow.f_HitFPosition, flip);

			local flyDir = hitPos - flyStartPos;
			local vSpeed = Vector3.Normalize(flyDir);
			local distance = flyDir.magnitude;
    
            vSpeed = vSpeed * speed;
    
			--Entity:playFly(fighter,skillShow,vSpeed,distance/speed,fighter_Pos,function()
			Entity:playFly(fighter,skillShow,vSpeed,distance/speed, flyStartPos,function()
            --Entity:playFly(fighter,skillShow,vSpeed,distance/speed,fighter_Pos,function()
                local eventData = Spine.EventData.New(tostring(skillShow.f_SkillID));
                eventData.Int = fighter.fighterId;
                eventData.Float = target.fighterId;
				eventData.String = "";
				skeletonAnimStateUserDataString[skillShow.f_SkillID] = skillShow
                local event = Spine.Event.New(0,eventData);
                event.Int = EnumConst.SpineEventType.HIT;
                UserDataEventDelegate2(event,eventData);
                local event2 = Spine.Event.New(0,eventData);
                event2.Int = EnumConst.SpineEventType.DAMAGE;
                UserDataEventDelegate2(event2,eventData);
            end);
        end
    end
end

-- 摄像机需要移动的时间
function BattleScene.GetCameraMoveTime(heroEndPos,cameraEndPosx)
	local speed = 0
	local maxDistanceX = 0
	for key, hero in pairs(tab_HeroList) do
		local tempEndPos = heroEndPos[key]
		local posx , posy,posz = Util.Lua_GetLocalPositionXYZ(hero.roleObj,0,0,0)
		local distance = tempEndPos[1] - posx
		if distance > maxDistanceX then
			maxDistanceX = distance
			speed = hero.speedRun
		end
	end
	return speed == 0 and 0 or maxDistanceX / speed
end